#include "painlessMesh.h"
#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555
Scheduler userScheduler; // to control your personal task
painlessMesh mesh;
SimpleList<uint32_t> nodes;
String inputString = "";     // a String to hold incoming data
bool stringComplete = false; // whether the string is complete
// User stub
void sendMessage(); // Prototype so PlatformIO doesn't complain
Task taskSendMessage(TASK_SECOND * 1, TASK_FOREVER, &sendMessage);
void sendMessage()
{
    digitalWrite(2, 0);
    String msg = "Hello from node ";
    msg += mesh.getNodeId();
    mesh.sendBroadcast(msg);
    Serial.printf("T[%u]: %s\n", mesh.getNodeId(), msg.c_str());
    taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
    digitalWrite(2, 1);
}
// Needed for painless library
void receivedCallback(uint32_t from, String &msg)
{
    int sleep, i;
    Serial.printf("R[%u]: %s\n", from, msg.c_str());
    i = sscanf(msg.c_str(), "DeepSleep%d", &sleep);
    if (i == 1)
    {
        delay(100);
        Serial.printf("--------SLEEP %ds--------\n", sleep);
        delay(3000);
        ESP.deepSleep(sleep);
    }
}
void newConnectionCallback(uint32_t nodeId)
{
    Serial.printf("--> New Connection, nodeId : %u\n", nodeId);
}
void changedConnectionCallback()
{
    Serial.printf("----------------\n");
    //  Serial.printf("Changed connections\n");
    nodes = mesh.getNodeList();

    Serial.printf("Num nodes: %d\n", nodes.size());
    Serial.printf("Connection list:\n");

    SimpleList<uint32_t>::iterator node = nodes.begin();
    while (node != nodes.end())
    {
        Serial.printf("-%u\n", *node);
        node++;
    }
    Serial.printf("----------------\n");
}

void nodeTimeAdjustedCallback(int32_t offset)
{
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
}

void setup()
{
    Serial.begin(115200);
    delay(3000);
    pinMode(2, OUTPUT);
    digitalWrite(2, 1);
    // mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
    mesh.setDebugMsgTypes(ERROR | STARTUP); // set before init() so that you can see startup messages

    mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
    mesh.onReceive(&receivedCallback);
    mesh.onNewConnection(&newConnectionCallback);
    mesh.onChangedConnections(&changedConnectionCallback);
    mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
    userScheduler.addTask(taskSendMessage);
    taskSendMessage.enable();
    Serial.printf("--------BEGIN---------\n");
    Serial.printf("Node:%u\n", mesh.getNodeId());
}

void loop()
{
    // it will run the user scheduler as well
    mesh.update();
}
void serialEvent()
{
    inputString = "";
    while (Serial.available())
    {
        // get the new byte:
        char inChar = (char)Serial.read();
        // add it to the inputString:
        inputString += inChar;
        // if the incoming character is a newline, set a flag so the main loop can
        // do something about it:
        if (inChar == '\n')
        {
            stringComplete = true;
        }
        delay(2);
    }
    Serial.println(inputString);
    mesh.sendBroadcast(inputString);
}